#include "platform/openal/openal_listener.hpp"
#include "AL/al.h"

namespace Xen {

void OpenALAudioListener::SetGain(float gain) {
    ALCall(alListenerf(AL_GAIN, gain));
    SetGain(1);
    SetPosition(glm::vec3(0, 0, 0));
    SetRotation(glm::vec3(0, 0, 0));
    SetVelocity(glm::vec3(0, 0, 0));
}

float OpenALAudioListener::GetGain() const {
    float gain;
    ALCall(alGetListenerf(AL_GAIN, &gain));
    return gain;
}

void OpenALAudioListener::SetPosition(const glm::vec3& pos) {
    ALCall(alListenerfv(AL_POSITION, glm::value_ptr(pos)));
}

glm::vec3 OpenALAudioListener::GetPosition() const {
    float position[3];
    ALCall(alGetListenerfv(AL_POSITION, position));
    return glm::vec3(position[0], position[1], position[2]);
}

void OpenALAudioListener::SetVelocity(const glm::vec3& vel) {
    ALCall(alListenerfv(AL_VELOCITY, glm::value_ptr(vel)));
}

glm::vec3 OpenALAudioListener::GetVelocity() const {
    float velocity[3];
    ALCall(alGetListenerfv(AL_VELOCITY, velocity));
    return glm::vec3(velocity[0], velocity[1], velocity[2]);
}

void OpenALAudioListener::SetRotation(const glm::vec3& rot) {
    glm::vec3 front = glm::rotate(glm::mat4(1.0f), glm::radians(rotation_.x), glm::vec3(1, 0, 0)) *
                      glm::rotate(glm::mat4(1.0f), glm::radians(rotation_.y), glm::vec3(0, 1, 0)) *
                      glm::rotate(glm::mat4(1.0f), glm::radians(rotation_.z), glm::vec3(0, 0, 1)) * glm::vec4(0, 0, -1, 1);
    glm::vec3 up = glm::rotate(glm::mat4(1.0f), glm::radians(rotation_.x), glm::vec3(1, 0, 0)) *
                   glm::rotate(glm::mat4(1.0f), glm::radians(rotation_.y), glm::vec3(0, 1, 0)) *
                   glm::rotate(glm::mat4(1.0f), glm::radians(rotation_.z), glm::vec3(0, 0, 1)) * glm::vec4(0, 1, 0, 1);

    float orentation[6] = {
        front.x, front.y, front.z,
        up.x, up.y, up.z
    };
    ALCall(alListenerfv(AL_ORIENTATION, orentation));
}

glm::vec3 OpenALAudioListener::GetRotation() const {
    return rotation_;
}

}
